import GameConfig from "../config/GameConfig";
import LanguageConfig from "../config/LanguageConfig";
import MyUserData from "../config/MyUserData";
import UserData from "../user/UserData";
import { Shake } from "./Shake";

/**
 * 辅助
 */
export default class Utils {
    /**
     * 遍历一级文件夹下的全部资源
     * @param url 一级路径
     * @param type 资源类型
     */
    static getFileByPath(url: string, type = cc.Asset): Array<string> {
        type = type || cc.Asset;
        let _url = url || "";
        let info = cc.resources["_config"].getDirWithPath(_url, type);
        let uuids = [];
        info.forEach((info) => {
            uuids.push(info.uuid)
        });
        //console.log("uuids:"+uuids);
        return uuids;
    }
    /**获取参数 */
    public static GetQueryValue1(queryName: string) {
        var reg = new RegExp("(^|&)" + queryName + "=([^&]*)(&|$)", "i");
        var r = window.location.search.substr(1).match(reg);
        if (r != null) {
            return decodeURI(r[2]);
        } else {
            return null;
        }
    }
    /**
     * 飘窗
     * @param content 内容
     * @param timeoutmills 延迟
     */
    public static toast(content: string, show = false, timeoutmills = 1): void {
        if (content == null) return;
        if (!show)
            //content = LanguageConfig.getText(content);
            cc.resources.load('prefabs/panel/toast', (err, prefab: cc.Prefab) => {
                let newNode: cc.Node = cc.instantiate(prefab);
                if (newNode) {
                    newNode.zIndex = 20000;
                    cc.director.getScene().getChildByName('Canvas').addChild(newNode);
                    newNode.getChildByName('label').getComponent(cc.Label).string = content;
                    newNode.opacity = 255;
                    cc.tween(newNode).delay(0.5).to(0.5, { opacity: 100 }).call(() => {
                    }).start();
                    cc.tween(newNode).delay(0.5).by(0.5, { y: 100 }).call(() => {
                        newNode.destroy();
                    }).start();
                }
            });
    }
    /**
     * 飘窗
     * @param content 内容
     * @param timeoutmills 延迟
     */
    public static toast2(content: string, show = false, timeoutmills = 1): void {
        if (content == null) return;
        if (!show)
            //content = LanguageConfig.getText(content);
            cc.resources.load('prefabs/panel/toast2', (err, prefab: cc.Prefab) => {
                let newNode: cc.Node = cc.instantiate(prefab);
                if (newNode) {
                    newNode.zIndex = 20000;
                    cc.director.getScene().getChildByName('Canvas').addChild(newNode);
                    newNode.getChildByName('label').getComponent(cc.RichText).string = content;
                    newNode.opacity = 255;
                    // cc.tween(newNode).delay(0.6).to(0.5, { opacity: 100 }).call(() => {
                    // }).start();
                    cc.tween(newNode).by(0.5, { x: -570 }).delay(0.3).by(0.3, { x: -600 , opacity: 20 }).call(() => {
                        newNode.destroy();
                    }).start();
                }
            });
    }
    /**缓存数据 */
    public static setItem(key: string, value: any) {
        if (typeof value == "object") value = JSON.stringify(value);
        key = GameConfig.gameName + "_" + GameConfig.version + "_" + key;
        localStorage.setItem(key, value);
    }
    /**获取缓存数据 */
    public static getItem(key: string) {
        key = GameConfig.gameName + "_" + GameConfig.version + "_" + key;
        let item = localStorage.getItem(key);
        return item;
    }

    // 检查内容是否包含敏感词
    public static  checkSensitiveWords(content) {
    // 遍历敏感词数组
    for (let i = 0; i < GameConfig.sensitiveWords.length; i++) {
      // 如果内容包含敏感词，则返回true
      if (content.includes(GameConfig.sensitiveWords[i])) {
        return true;
      }
    }
    // 如果没有找到敏感词，则返回false
    return false;
  }
    /**获取变化次数 */
    public static getTimes(time: number = 1, dur: number = 0) {
        if (time < 0) {
            console.error("error time:" + time);
            return time;
        }
        let times = 500;
        if (time == 0) {//默认参数
            if (dur < 10) {
                time = 0.02;
            } else if (dur < 100) {
                time = 0.05;
            } else if (dur < 1000) {
                time = 0.08;
            } else if (dur < 10000) {
                time = 0.1;
            } else if (dur < 100000) {
                time = 0.2;
            } else if (dur < 1000000) {
                time = 0.3;
            } else {
                time = 0.5;
            }
        } else {
            times = 30;
        }
        return times * time;
    }
    /**获取某年某月的天数 */
    public static mGetDate(year: number, month: number) {
        var d = new Date(year, month, 0);
        return d.getDate();
    }
    /**
     * 时间格式化
     * @param time 时间 毫秒数
     * @param type 类型 转换类型 0=yy/mm/dd,1=yy-mm-dd,2=hh:mm:ss\nmm/dd,3:yy-mm-dd hh:mm (GMT+8:00)
     */
    public static getParseTime(time: number, type: number = 0) {
        let date = new Date(time);
        let year: any = date.getFullYear();
        let month: any = date.getMonth() + 1;
        month = month < 10 ? "0" + month : month
        let day: any = date.getDate();
        day = day < 10 ? "0" + day : day
        let hour: any = date.getHours();
        hour = hour < 10 ? "0" + hour : hour
        let minute: any = date.getMinutes();
        minute = minute < 10 ? "0" + minute : minute
        let second: any = date.getSeconds();
        second = second < 10 ? "0" + second : second;
        if (type == 0) {
            return year + "/" + month + "/" + day;
        } else if (type == 1) {
            return year + "-" + month + "-" + day;
        } else if (type == 2) {
            return hour + ":" + minute + ":" + second + "\n" + month + "/" + day;
        } else if (type == 3) {
            return year + "/" + month + "/" + day + " " + hour + ":" + minute + " (GMT+7:00)";
        } else if (type == 4) {
            return year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
        }
    }

    /**时间格式转换
     * 
     */
    public static convertSecondsToTime(seconds: number): string {
        const hours: number = Math.floor(seconds / 3600);
        const minutes: number = Math.floor((seconds % 3600) / 60);
        const remainingSeconds: number = seconds % 60;
    
        // 格式化时间
        const formattedHours: string = hours.toString().padStart(2, '0');
        const formattedMinutes: string = minutes.toString().padStart(2, '0');
        const formattedSeconds: string = remainingSeconds.toString().padStart(2, '0');
    
        // 如果有小时，则返回小时:分钟:秒
        if (hours > 0) {
            return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`;
        }
    
        // 否则，只返回分钟:秒
        return `${formattedMinutes}:${formattedSeconds}`;
    }
    /**获取图集 */
    public static getAtlas(spriteAtlasKey: string, callBack: Function, language = LanguageConfig.gameLanguage) {
        if (!spriteAtlasKey) return;
        let path = LanguageConfig.languagePath[language];
        let filePath = "i18n/" + path + "/" + spriteAtlasKey;
        cc.resources.load(filePath, cc.SpriteAtlas, null, (error, asset: cc.SpriteAtlas) => {
            if (error) return console.error("load error path:" + filePath);
            callBack(asset);
        });
    }

    /**格式化金币 */
    public static parseCoin(coin: number) {
        let fixed = GameConfig.versionType == 2 ? 0 : 2;
        if (coin < 1000) return "" + coin.toFixed(fixed);
        let num = Math.floor(coin).toString(), result = '';
        let last = coin.toFixed(fixed).split(".")[1];
        while (num.length > 3) {
            result = ',' + num.slice(-3) + result;
            num = num.slice(0, num.length - 3);
        }
        if (num) { result = num + result; }
        return result + (fixed ? ("." + last) : "");
    }

    public static timeOffset: number = 0;
    public static getServerTime() {
        return new Date().getTime() + Utils.timeOffset;
    }

    public static loadAsync<T extends typeof cc.Asset>(url: string, type: T): Promise<InstanceType<T>> {
        return new Promise<any>((resolve, reject) => {
            // cc.loader.loadRes(url, type, (err: Error, res: any) => {
            //     if (!err) {
            //         resolve(res);
            //     } else {
            //         reject('UtilRes.loadSync url:' + url + ',err:' + err);
            //     }
            // });
            cc.resources.load(url, type, function (err, res: any) {
                if (!err) {
                    resolve(res);
                } else {
                    reject('UtilRes.loadSync url:' + url + ',err:' + err);
                }
            })
        });
    }

    public static async asyncWrap<T, U = any>(promise: Promise<T>): Promise<[T | null, U | null]> {
        try {
            const data = await promise;
            const result: [T, null] = [data, null];
            return result;
        } catch (err) {
            const result_1: [null, U] = [null, err];
            return result_1;
        }
    }

    public static cachePlist = []

    public static async createPlist(resUrl: string): Promise<cc.SpriteAtlas> {
        let signs = resUrl.split("/")
        let sign = signs[signs.length - 1]
        if (Utils.cachePlist[sign]) {
            //console.log("cachePlist:",sign)
            return Utils.cachePlist[sign]
        }
        let [atlas, err] = await Utils.asyncWrap<cc.SpriteAtlas, string>(Utils.loadAsync(resUrl, cc.SpriteAtlas));
        if (err) {
            cc.error('Utils.createActor resUrl:' + resUrl + ',err:' + err);
            return null;
        }
        Utils.cachePlist[sign] = atlas
        return atlas;
    }

    public static async createSpr(resUrl: string): Promise<cc.SpriteFrame> {
        let [spr, err] = await Utils.asyncWrap<cc.SpriteFrame, string>(Utils.loadAsync(resUrl, cc.SpriteFrame));
        if (err) {
            cc.error('Utils.createActor resUrl:' + resUrl + ',err:' + err);
            return null;
        }
        return spr;
    }

    public static async createActorNode(resUrl: string): Promise<cc.Node> {
        let [prefab, err] = await Utils.asyncWrap<cc.Prefab, string>(Utils.loadAsync(resUrl, cc.Prefab));
        if (err) {
            cc.error('Utils.createActor resUrl:' + resUrl + ',err:' + err);
            return null;
        }
        const node = cc.instantiate(prefab);
        return node;
    }

    //取值范围
    public static rangeInDefined(current, min, max) {
        return Math.max(min, current) == Math.min(current, max);
    }

    public static _findInChildren(node: cc.Node, name: string): cc.Node {
        var x = node.getChildByName(name);
        if (x) return x;
        if (node.childrenCount == 0) return null;

        for (var i = 0; i < node.childrenCount; ++i) {
            var tmp = Utils._findInChildren(node.children[i], name);
            if (tmp) return tmp;
        }
        return null;
    }

    public static world2local(other: cc.Node, self: cc.Node) {
        let targetPos = other.convertToWorldSpaceAR(cc.Vec3.ZERO);
        let tempPos = self.convertToNodeSpaceAR(targetPos);

        return tempPos
    }

    public static getDistance(p1: cc.Vec3, p2: cc.Vec3): number {
        return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2));
    }

    public static fgRangeRand(min: number, max: number): number {
        let rnd: number = Math.random();
        return Math.floor(rnd * (max - min) + min);
    }

    public static Shake(target: cc.Node, duration: number, strength_x: number, strength_y: number) {
        let act = Shake.create(duration, strength_x, strength_y);
        act.startWithTarget(target);
        target.runAction(act);
    }

    public static formatNumber(nStr) {
        nStr += ''; //数字转换为字符 
        let x = nStr.split('.'); //按照小数点分隔
        let x1 = x[0]; //整数部分
        let x2 = x.length > 1 ? '.' + x[1] : ''; //小数部分
        var rgx = /(\d+)(\d{3})/; //正则式定义
        while (rgx.test(x1)) { //正则式匹配
            x1 = x1.replace(rgx, '$1' + ',' + '$2'); //正则式替换
        }
        return x1 + x2;
    }
    //改变文字颜色
    public static setValueColor(node, v) {
        // 白 255,255,255
        // 万 #0177B2   1,119,178
        // 十万 #00AC2D 0,172,45
        // 百万 #F77900 247,121,0
        // 千万 #E03DCE 224,61,206
        // 亿 #ED2B11 237,43,17
        // 十亿 #F6D918 246,217,24
        // 百亿 #16F0EA 22,240,234
        // 无穷 ∞
        let colorList = [
            cc.color(255, 255, 255),
            cc.color(255, 255, 255), 
            cc.color(255, 255, 255),
            cc.color(255, 255, 255),
            cc.color(0, 128, 192, 255),
            cc.color(0, 190, 50, 255),
            cc.color(255, 125, 0, 255),
            cc.color(250, 68, 230, 255),
            cc.color(255, 0, 0, 255),
            cc.color(255, 255, 0, 255),
            cc.color(23, 255, 247, 255),
        ]
        node.color = cc.color(255, 255, 255)
        for (let i = 0; i < 10; i++) {
            //const element = array[i];
            if (v >= (10 ** i)) { //- 1
                node.color = colorList[i]
            }
        }
    }
    //根据变色字符进行颜色切换
    public static setSgTextColor(node, v) {
        let color_text = {
            "/C08":cc.color().fromHEX("#ae752d"),
            "/C02":cc.color().fromHEX("#90d483"),
            "/C16":cc.color().fromHEX("#28ed48"),
            "/C30":cc.color().fromHEX("#00ace5"),
            "/C31":cc.color().fromHEX("#c74de5"),
            "/C01":cc.color().fromHEX("#e4c300"),
            "/C04":cc.color().fromHEX("#f77e00"),
            "/C35":cc.color().fromHEX("ff0000")
        }
        if (!node) return color_text[v]
        node.color = cc.color(255, 255, 255)
        if (color_text[v]) {
            node.color = color_text[v]
        }

    }
    //根据变色字符进行颜色切换
    public static sgParseText(text: string): string {
        const colorMap: { [key: string]: string } = {
          "/C09": '#B9B9B9',
          "/C16": '#28F049',
          "/C17": '#F4F112',
          "/C18": '#ffffff',
          "/C23": '#28F049',
          "/C25": '#EF3452',
          "/C26": '#FF0E30',
          "/C27": '#F2DF06',
          "/C08":"#ae752d",
          "/C02":"#90d483",
          "/C30":"#00ace5",
          "/C31":"#c74de5",
          "/C32":"#60FF00",
          "/C01":"#e4c300",
          "/C04":"#f77e00",
          "/C35":"ff0000",
          "/C47":"#FF7EF8"
        };
      

          // 使用正则表达式查找所有的颜色代码和后续的文本
        const regex = /\/C\d{2}[\s\S]*?(?=\/C\d{2}|$)/g;


        // 替换文本中的颜色代码和内容
        return text.replace(regex, (match) => {
            // 提取颜色代码
            const colorCode = match.substring(0, 4);
            // 提取内容
            const content = match.substring(4);
            // 获取对应的颜色值
            const color = colorMap[colorCode] || '#ffffff'; // 如果没有匹配到颜色代码，则默认为白色
            //console.log(colorCode, color, content);
            // 返回替换后的字符串
            return `<color=${color}>${content}</c>`;
        });
      }


    //生成随机id
    public static guid() {
        return 'xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            var r = Math.random() * 16 | 0,
                v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    //partType to skinname 表部件类型
    public static pT2SkName(idx) {
        let skinname = null
        let tlist = {
            0: 2,
            1: 4,
            3: 9,
            4: 5,
            5: 6,
            6: 7, //手部需要两个 7、8
            7: 10,
            9: 13 //武器需要两个 13..
        }
        skinname = tlist[idx]
        return skinname
    }
    //UI面板编号
    public static sk2PtName(idx) {
        let ptname = null
        let tlist = {
            2: 0,
            4: 1,
            9: 3,
            5: 4,
            6: 5,
            7: 6, //手部需要两个 7、8
            8: 6, //手部需要两个 7、8
            10: 7,
            13: 9 //武器需要两个 13..
        }
        ptname = tlist[idx]
        return ptname
    }

    public static deepCopy(data) {
        return JSON.parse(JSON.stringify(data))
    }

    public static savePlayerData() {
        cc.sys.localStorage.setItem('playerData', JSON.stringify(MyUserData.playerData));
    }
    public static loadPlayerData() {
        let data = cc.sys.localStorage.getItem('playerData');
        if (data) {
            MyUserData.playerData = JSON.parse(data);
        } else {
            // 没有存档数据时的默认处理
        }
    }
}
